<?php
declare (strict_types=1);

namespace app\common\model;

use addons\Pay\facade\Pay;
use addons\Target\facade\Target;
use app\common\controller\Bonus;
use think\facade\Cache;
use think\facade\Event;

class OrderTemporary extends Order
{
    public static function setTemporary($param, $user): array
    {
        try {
            if ($param['type'] == 1) {
                $result = ProductSpec::getSettled($param, $user);
            } else {
                $result = ProductCart::getSettled($param['cart_id'], $user);
            }
            if ($result['code'] != 1) {
                throw new \Exception($result['msg']);
            }
            $productTemporary = $result['data'];
            if (empty($productTemporary)) {
                throw new \Exception('服务器错误，请稍后再试');
            }
            Cache::delete('productTemporaryCartId_' . $user->id);
            //缓存购物车标识
            if (!empty($param['cart_id'])) {
                Cache::set('productTemporaryCartId_' . $user->id, $param['cart_id']);
            }
            Cache::set('productTemporary_' . $user->id, $productTemporary);

        } catch (\Exception $e) {

            return ['code' => -1, 'msg' => $e->getMessage()];
        }

        return ['code' => 4, 'msg' => 'success', 'url' => url('order/index')->build()];
    }

    public static function getTemporary($uid): array
    {
        try {
            $temporary = Cache::get('productTemporary_' . $uid);
            if (empty($temporary)) {
                throw new \Exception('加载失败，请再试一次！');
            }
            $temporary['address'] = Address::getDefault($uid);

        } catch (\Exception $e) {

            return ['code' => -1, 'msg' => $e->getMessage()];
        }

        return ['code' => 1, 'msg' => 'success', 'data' => $temporary];
    }

    public static function submit($param, $user): array
    {
        try {
            if (empty($param['address_id'])) {
                throw new \Exception('请选择收货地址');
            }
            $address = Address::where(['id' => $param['address_id']])->find();
            if (empty($address)) {
                throw new \Exception('收货地址错误，请重新选择');
            }
            $temporary = Cache::get('productTemporary_' . $user->id);
            $temporary['address_id'] = $param['address_id'];
            $temporary['remark'] = !empty($param['remark']) ? $param['remark'] : '';

            return self::createOrder($temporary, $user, $address);
        } catch (\Exception $e) {

            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    public static function createOrder($param, $user, $address): array
    {
        $time = time();
        $amount = $num = $order_type = 0;
        foreach ($param['product'] as &$children) {
            $product = Product::where(['id' => $children['pid'], 'status' => 1])->find();
            if (empty($product)) {
                return ['code' => -1, 'msg' => '商品《' . $product->title . '》已下架'];
            }
            if ($product->spec_open == 2) {
                $specValue = ProductSpec::where(['pid' => $children['pid'], 'merge_title' => $children['spec']])->find();
                if (empty($specValue) || $children['num'] > $specValue->stock) {
                    return ['code' => -1, 'msg' => '商品《' . $product->title . '-' . $children['spec'] . '》库存不足'];
                }
                $children['icon'] = $specValue->icon ?: $product->icon;
                $children['vip_price'] = $specValue->vip_price;
                //减少库存
                $specValue->stock -= $children['num'];
                $specValue->save();
            } else {
                if ($children['num'] > $product->stock) {
                    return ['code' => -1, 'msg' => '商品《' . $product->title . '》库存不足'];
                }
                $children['icon'] = $product->icon;
                $children['vip_price'] = $product->vip_price;
            }
            $children['amount'] = round($children['vip_price'] * $children['num'], 2);
            $num += $children['num'];
            //订单总价格
            $amount += $children['amount'];
            //增加销量
            $product->sales += $children['num'];
            $product->stock -= $children['num'];
            $product->save();
            //定义订单类别
            $order_type = $product->cate_1;
        }
        parent::startTrans();
        try {
            $new = parent::create([
                'sn' => 'T' . date('YmdHis') . generateRandom() . $user->id,
                'uid' => $user->id,
                'order_type' => $order_type,
                'num' => $num,
                'total_amount' => $amount,
                'real_amount' => $amount,
                'address_id' => !empty($address) ? $address->id : 0,
                'receiver' => !empty($address) ? $address->nickname : '',
                'receiver_tel' => !empty($address) ? $address->tel : '',
                'province' => !empty($address) ? $address->province : '',
                'city' => !empty($address) ? $address->city : '',
                'district' => !empty($address) ? $address->district : '',
                'address_details' => !empty($address) ? $address->details : '',
                'remark' => $param['remark'],
                'status' => 1,
                'expire_time' => $time + 1800
            ]);
            $walk = ['order_id' => $new->id, 'uid' => $user->id];
            array_walk($param['product'], function (&$value, $key, $walk) {
                $value = array_merge($value, $walk);
            }, $walk);
            (new OrderProduct())->insertAll($param['product']);
            $cart_id = Cache::get('productTemporaryCartId_' . $user->id);
            if ($cart_id) {
                ProductCart::destroy(['id' => $cart_id], true);
                Cache::delete('productTemporaryCartId_' . $user->id);
            }
            Cache::delete('productTemporary_' . $user->id);

            parent::commit();
        } catch (\Exception $e) {
            parent::rollback();

            return ['code' => -1, 'msg' => $e->getMessage()];
        }

        return ['code' => 1, 'msg' => 'success', 'data' => $new->id];
    }

    public static function getPayment($id, $user): array
    {
        try {
            $info = parent::field('id,sn,order_type,real_amount,expire_time,status')
                ->where(['id' => $id, 'uid' => $user->id])->find();
            if (empty($info)) {
                throw new \Exception('无效订单');
            }
            if ($info->getData('status') != 1) {
                throw new \Exception('订单已支付或已失效');
            }
            $data['order'] = $info;
            $data['method'] = self::payWay($info->order_type);

        } catch (\Exception $e) {

            return ['code' => -1, 'msg' => $e->getMessage()];
        }

        return ['code' => 1, 'msg' => 'success', 'data' => $data];
    }

    public static function payWay($order_type = ''): array
    {
        return match ($order_type) {
            default => self::getPaymentMethod(['currency', 'bonus'])
        };
    }

    public static function getPaymentMethod($data): array
    {
        $method = [];
        foreach ($data as $item) {
            if (in_array($item, ['wechat', 'alipay'])) {
                $is_pay = 0;
                $icon = $item;
            } else {
                $is_pay = 1;
                $icon = 'wallet';
            }
            $method[] = [
                'title' => get_pay_way($item),
                'pay_way' => $item,
                'icon' => '/static/admin/img/' . $icon . '.png',
                'is_pay_password' => $is_pay
            ];
        }

        return $method;
    }

    public static function payment($param, $user): array
    {
        try {
            $info = parent::where(['id' => $param['id']])->find();
            if ($info->getData('status') != 1) {
                throw new \Exception('订单已支付或已失效');
            }
            $pay_way = $param['pay_way'];
            switch ($pay_way) {
                case "currency":
                case "bonus":
                    if (md5($param['pay_password']) != $user->pay_password) {
                        throw new \Exception('支付密码错误');
                    }
                    if ($info->real_amount > $user->assets->$pay_way) {
                        throw new \Exception(get_pay_way($pay_way) . '账户余额不足');
                    }
                    return self::operations($info, $user, $pay_way);
//                case "wechat":
//                    $return_url = request()->domain() . '/index/order/myOrder?type=2';
//                    $notifyUrl = request()->domain() . '/time/callback/wechat';
//                    $options = Pay::setDriver('WeChat')
//                        ->setReturnUrl($return_url)
//                        ->basic('购买商品', $info->sn, $info->real_amount, $notifyUrl)
//                        ->create('MWEB');
//
//                    return ['code' => 4, 'msg' => 'success', 'data' => $options];
//                case "alipay":
//                    $return_url = request()->domain() . '/index/order/myOrder?type=2';
//                    $notifyUrl = request()->domain() . '/time/callback/alipay';
//                    $options = Pay::setDriver('AliPay')
//                        ->setReturnUrl($return_url)
//                        ->basic('购买商品', $info->sn, $info->real_amount, $notifyUrl)
//                        ->create('Wap');
//
//                    return ['code' => 3, 'msg' => 'success', 'data' => $options];
                default:
                    throw new \Exception('暂未开放');
            }

        } catch (\Exception $e) {

            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    public static function operations($info, $user, $pay_way, $transaction_id = ''): array
    {
        parent::startTrans();
        try {
            $time = time();
            $info->status = 2;
            if ($transaction_id) {
                $info->transaction_id = $transaction_id;
            }
            $info->pay_state = 1;
            $info->pay_way = $pay_way;
            $info->pay_time = $time;
            $info->save();
            if (!in_array($pay_way, ['wechat', 'alipay'])) {
                Target::Account()->basics($user->id, $pay_way, $info->real_amount, '购买商品', '-')
                    ->createNormal();
            }
            if ($user->is_active == 1) {
                $user->is_active = 2;
                $user->active_type = 1;
                $user->active_time = $time;
                if ($user->parent_id) {
                    User::where(['id' => $user->parent_id])->inc('push_num')->save();
                    $renewData[] = ['fx' => '+', 'field' => 'team_num', 'num' => 1];
                }
                Event::trigger('Statistics', ['key' => 'formal_user', 'value' => 1]);
            }
            $user->my_total += $info->real_amount;
            $user->save();
            $renewData[] = ['fx' => '+', 'field' => 'team_total', 'num' => $info->real_amount];
            Relation::renewTeamTotal($user->id, $renewData);
            Bonus::teamBonus($user->id, $info->real_amount);
            Level::upgrade($user->id);
            Event::trigger('Statistics', ['key' => 'income', 'value' => $info->real_amount]);

            parent::commit();
        } catch (\Exception $e) {
            parent::rollback();

            return ['code' => -1, 'msg' => $e->getMessage()];
        }

        return ['code' => 1, 'msg' => '支付成功', 'url' => url('order/success')->build()];
    }

    public static function edit($param, $user): array
    {
        parent::startTrans();
        try {
            $info = parent::where(['id' => $param['id'], 'uid' => $user->id])->find();
            if (empty($info)) {
                throw new \Exception('此订单不存在');
            }
            switch ($param['type']) {
                case 'cancel': //取消订单
                    if ($info->getData('status') != 1 || $info->pay_state) {
                        throw new \Exception('此订单已支付，无法取消');
                    }
                    self::cancel($info);
                    $msg = '订单已取消';
                    break;
                case "remind": //提醒发货
                    if ($info->getData('status') != 2) {
                        throw new \Exception('此订单未支付或已发货');
                    }
                    if ($info->is_remind) {
                        throw new \Exception('您已提醒发货了');
                    }
                    $info->is_remind = 1;
                    $info->remind_time = time();
                    $info->save();
                    $msg = '已提醒发货';
                    break;
                case "receipt": //确认收货
                    if ($info->getData('status') != 3) {
                        throw new \Exception('此订单无需收货');
                    }
                    self::receipt($info);
                    $msg = '已确认收货';
                    break;
                default:
                    throw new \Exception('操作有误');
            }

            parent::commit();
        } catch (\Exception $e) {
            parent::rollback();

            return ['code' => -1, 'msg' => $e->getMessage()];
        }

        return ['code' => 1, 'msg' => $msg];
    }

    public static function cancel($order): bool|string
    {
        try {
            $order->status = 6;
            $order->cancel_time = time();
            $order->save();
            Event::trigger('Operation', $order->id);

        } catch (\Exception $e) {

            return $e->getMessage();
        }

        return true;
    }

    public static function receipt($order, $is_auto = false): bool|string
    {
        try {
            $time = time();
            $order->status = 5;
            $order->receipt_time = $time;
            $order->finish_time = $time;
            if ($is_auto) $order->auto_receipt_time = $time;
            $order->save();

        } catch (\Exception $e) {

            return $e->getMessage();
        }

        return true;
    }

    /**
     * 支付超时自动取消订单
     * 定时
     */
    public static function autoCancel(): array
    {
        parent::startTrans();
        try {
            parent::where(['status' => 1, 'pay_state' => 0])->where('expire_time', '<=', time())->select()->each(function ($item) {
                self::cancel($item);
            });

            parent::commit();
        } catch (\Exception $e) {
            parent::rollback();
            Logs::write('logs/autoCancel.log', $e->getMessage());

            return ['code' => -1, 'msg' => $e->getMessage()];
        }

        return ['code' => 1, 'msg' => '执行成功'];
    }

    /**
     * 自动确认收货
     * 定时
     */
    public static function autoReceipt(): bool|string
    {
        try {
            parent::where(['status' => 3])->where('auto_receipt_time', '<=', time())->select()->each(function ($item) {
                self::receipt($item, true);
            });

        } catch (\Exception $e) {

            return $e->getMessage();
        }

        return true;
    }
}